<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" >

  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/turbolinks/5.2.0/turbolinks.js" integrity="sha256-iM4Yzi/zLj/IshPWMC1IluRxTtRjMqjPGd97TZ9yYpU=" crossorigin="anonymous"></script>
  <link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
  <link href="https://fonts.googleapis.com/css?family=Cousine|Inconsolata" rel="stylesheet">
  <link rel="shortcut icon" type="image/png" href="/favicon.png">

  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/css/fontawesome-all.min.css">
  <link rel="stylesheet" href="/css/css/work-sans-v7.css">
  <script src="/js/main.js"></script>

  <!-- Begin Jekyll SEO tag v2.6.1 -->
<title>PY: Follow A User | Hive Developer</title>
<meta name="generator" content="Jekyll v4.0.0" />
<meta property="og:title" content="PY: Follow A User" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="How to follow or unfollow an author using Python." />
<meta property="og:description" content="How to follow or unfollow an author using Python." />
<link rel="canonical" href="follow_a_user.html" />
<meta property="og:url" content="follow_a_user.html" />
<meta property="og:site_name" content="Hive Developer" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2020-08-26T11:52:22-07:00" />
<script type="application/ld+json">
{"description":"How to follow or unfollow an author using Python.","mainEntityOfPage":{"@type":"WebPage","@id":"follow_a_user.html"},"@type":"BlogPosting","url":"follow_a_user.html","headline":"PY: Follow A User","dateModified":"2020-08-26T11:52:22-07:00","datePublished":"2020-08-26T11:52:22-07:00","@context":"https://schema.org"}</script>
<!-- End Jekyll SEO tag -->


  
</head>
<body>
<header>
  <h1>
    <button type="button" class="open-nav" id="open-nav"></button>
    <a href="/"  class="logo-link"><img src="/images/logotype_black.svg" height="40" alt="Hive Developer logo"></a>
  </h1>

  
  <form action="/search/" method="get">
    <input type="text" name="q" id="search-input" placeholder="Search">
    <input type="submit" value="Search" style="display: none;">
  </form>
  

  <div id="sidebar" class="sidebar">
	
	
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/">
		<h6 class="ctrl-nav-section title">Introduction</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/#introduction-welcome">Welcome to Hive</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/quickstart/">
		<h6 class="ctrl-nav-section title">Quickstart</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/quickstart/#quickstart-choose-library">Choose Library</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-hive-full-nodes">Hive Nodes</a></li>
						
					
						
						<li><a href="/quickstart/#quickstart-testnet">Hive Testnet</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/tutorials/">
		<h6 class="ctrl-nav-section title">Tutorials</h6>
		<ul class="cont-nav-section content">
			
				
					
						<li><a href="/tutorials/#tutorials-javascript">Javascript</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-python">Python</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-ruby">Ruby</a></li>
					
				
					
						<li><a href="/tutorials/#tutorials-recipes">Recipes</a></li>
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/services/">
		<h6 class="ctrl-nav-section title">Services</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/services/#services-hive-blog">hive.blog</a></li>
						
					
						
						<li><a href="/services/#services-hivesigner">HiveSigner</a></li>
						
					
						
						<li><a href="/services/#services-jussi">Jussi</a></li>
						
					
						
						<li><a href="/services/#services-imagehoster">ImageHoster</a></li>
						
					
						
						<li><a href="/services/#services-dhf">DHF</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/apidefinitions/">
		<h6 class="ctrl-nav-section title">Appbase API</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/apidefinitions/#apidefinitions-condenser-api">Condenser Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-bridge">Bridge</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-by-key-api">Account By Key Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-account-history-api">Account History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-block-api">Block Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-database-api">Database Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-debug-node-api">Debug Node Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-follow-api">Follow Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-jsonrpc">Jsonrpc</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-market-history-api">Market History Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-network-broadcast-api">Network Broadcast Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rc-api">Rc Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-reputation-api">Reputation Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-rewards-api">Rewards Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-tags-api">Tags Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-transaction-status-api">Transaction Status Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-witness-api">Witness Api</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops">Broadcast Ops</a></li>
						
					
						
						<li><a href="/apidefinitions/#apidefinitions-broadcast-ops-communities">Broadcast Ops Communities</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/resources/">
		<h6 class="ctrl-nav-section title">Resources</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/resources/#resources-overview">Overview</a></li>
						
					
						
						<li><a href="/resources/#resources-client-libs">Client Libraries</a></li>
						
					
						
						<li><a href="/resources/#resources-bluepaper">Bluepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-whitepaper">Whitepaper</a></li>
						
					
						
						<li><a href="/resources/#resources-tools">Tools</a></li>
						
					
						
						<li><a href="/resources/#resources-hivesigner-libs">Hivesigner Libs</a></li>
						
					
						
						<li><a href="/resources/#resources-hive-keychain">Hive Keychain</a></li>
						
					
						
						<li><a href="/resources/#resources-developeradvocate">Community & Help</a></li>
						
					
				
			
		</ul>
	</section>
	
		
    <section class="pnl-main-nav-section main-nav-section" url="/glossary/">
		<h6 class="ctrl-nav-section title">Glossary</h6>
		<ul class="cont-nav-section content">
			
				
					
					
						
						<li><a href="/glossary/#glossary-chain-basics">Chain Basics</a></li>
						
					
						
					
						
						<li><a href="/glossary/#glossary-governance">Governance</a></li>
						
					
						
						<li><a href="/glossary/#glossary-transactions">Transactions</a></li>
						
					
						
						<li><a href="/glossary/#glossary-api">API</a></li>
						
					
						
						<li><a href="/glossary/#glossary-market">Market</a></li>
						
					
				
			
		</ul>
	</section>
	
</div>



  <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
</header>
<div class="main" id="top">
  <div class="hero">
    <h1 class="hero__h1">Hive Developer Portal </h1>
    <img class="hero__img" src="/images/honey-comb-92.png" style="position: relative; top: 10px;" />
  </div>
  <section id="tutorials-python-follow-a-user" class="row tutorials-python-follow-a-user">
	<h3>
		<a id="tutorials-python-follow-a-user">
			PY: Follow A User
			
		</a>
	</h3>
	
		<span class="description"><p>How to follow or unfollow an author using Python.</p>
</span>
	

	<p><span class="fa-pull-left top-of-tutorial-repo-link"><span class="first-word">Full</span>, runnable src of <a href="https://gitlab.syncad.com/hive/devportal/-/tree/master/tutorials/python/tutorials/18_follow_a_user">Follow A User</a> can be downloaded as part of: <a href="https://gitlab.syncad.com/hive/devportal/-/tree/master/tutorials/python">tutorials/python</a>.</span>
<br /></p>

<p>In this tutorial we will explain and show you how to follow or unfollow any author on the <strong>Steem</strong> blockchain using the <code class="highlighter-rouge">commit</code> class found within the <a href="https://github.com/steemit/steem-python">steem-python</a> library.</p>

<h2 id="intro">Intro</h2>

<p>The Steem python library has a built-in function to transmit transactions to the blockchain. We are using the <code class="highlighter-rouge">follow</code> and <code class="highlighter-rouge">unfollow</code> methods found within the <code class="highlighter-rouge">commit</code> class in the the library. Before we can follow/unfollow we first have to check what the current ‘follow status’ is of the author. We use another function for this which is explained in the tutorial entitled <code class="highlighter-rouge">get_following_and_follower_list</code>. There are 3 parameters within the <code class="highlighter-rouge">follow/unfollow</code> methods:</p>

<ol>
  <li><em>follow/unfollow</em> - The name of the author that will be followed/unfollowed</li>
  <li><em>what</em> - The list of states to be followed. Currently this defaults to <code class="highlighter-rouge">blog</code> as it’s the only option available on the block chain at this stage</li>
  <li><em>account</em> - The name of the account that is executing the follow/unfollow</li>
</ol>

<h2 id="steps">Steps</h2>

<ol>
  <li><a href="#setup"><strong>App setup</strong></a> - Library install and import. Connection to testnet</li>
  <li><a href="#userinfo"><strong>User information and steem node</strong></a> - Input user information and connection to Steem node</li>
  <li><a href="#authorstat"><strong>Check author status</strong></a> - Validity check on requested autor to follow</li>
  <li><a href="#followstat"><strong>Follow status</strong></a> - Check whether specified author is already followed</li>
  <li><a href="#commit"><strong>Follow/Unfollow commit</strong></a> - Follow/unfollow commit to the blockchain</li>
</ol>

<h4 id="1-app-setup-">1. App setup <a name="setup"></a></h4>

<p>In this tutorial we use 3 packages:</p>

<ul>
  <li><code class="highlighter-rouge">steem</code> - steem-python library and interaction with Blockchain</li>
  <li><code class="highlighter-rouge">pick</code> - helps select the query type interactively</li>
</ul>

<p>We import the libraries and connect to the <code class="highlighter-rouge">testnet</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">steembase</span>
<span class="kn">import</span> <span class="nn">steem</span>
<span class="kn">from</span> <span class="nn">pick</span> <span class="kn">import</span> <span class="n">pick</span>

<span class="n">steembase</span><span class="o">.</span><span class="n">chains</span><span class="o">.</span><span class="n">known_chains</span><span class="p">[</span><span class="s">'STEEM'</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'chain_id'</span><span class="p">:</span> <span class="s">'79276aea5d4877d9a25892eaa01b0adf019d3e5cb12a97478df3298ccdd01673'</span><span class="p">,</span>
    <span class="s">'prefix'</span><span class="p">:</span> <span class="s">'STX'</span><span class="p">,</span> <span class="s">'steem_symbol'</span><span class="p">:</span> <span class="s">'STEEM'</span><span class="p">,</span> <span class="s">'sbd_symbol'</span><span class="p">:</span> <span class="s">'SBD'</span><span class="p">,</span> <span class="s">'vests_symbol'</span><span class="p">:</span> <span class="s">'VESTS'</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Because this tutorial alters the blockchain we connect to the testnet so we don’t create spam on the production server.</p>

<h4 id="2-user-information-and-steem-node">2. User information and steem node<a name="userinfo"></a></h4>

<p>We also require the <code class="highlighter-rouge">private posting key</code> of the user that wishes to follow a selected author in order to commit the action to the blockchain. This is why we have to specify this along with the <code class="highlighter-rouge">testnet</code> node. The values are supplied via the terminal/console before we initialise the steem class. We have supplied a test account, <code class="highlighter-rouge">cdemo</code> to use with this tutorial but any demo account set up on the testnet can be used.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#capture user information
</span><span class="n">username</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Please enter your username: '</span><span class="p">)</span>
<span class="n">postingkey</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Please enter your private posting key: '</span><span class="p">)</span>

<span class="c1">#connect node and private posting key, demo account being used: cdemo, posting key: 5JEZ1EiUjFKfsKP32b15Y7jybjvHQPhnvCYZ9BW62H1LDUnMvHz
</span><span class="n">s</span> <span class="o">=</span> <span class="n">steem</span><span class="o">.</span><span class="n">Steem</span><span class="p">(</span><span class="n">nodes</span><span class="o">=</span><span class="p">[</span><span class="s">'https://testnet.steem.vc'</span><span class="p">],</span> <span class="n">keys</span><span class="o">=</span><span class="p">[</span><span class="n">postingkey</span><span class="p">])</span>
</code></pre></div></div>

<h4 id="3-check-author-status">3. Check author status<a name="authorstat"></a></h4>

<p>To insure the validity of the <code class="highlighter-rouge">follow</code> process, we first check to see if the <code class="highlighter-rouge">author</code> provided by the user is in fact an active username. This is done with a simple call to the blockchain which returns an array of all the user information. If the author does not exist, the return value is <code class="highlighter-rouge">null</code>.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#capture variables
</span><span class="n">author</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s">'Author to follow: '</span><span class="p">)</span>

<span class="c1">#check author status
</span><span class="n">result</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get_account</span><span class="p">(</span><span class="n">author</span><span class="p">)</span>
</code></pre></div></div>

<p>Once the author name is confirmed to be valid we can move on to check the follow status of that author.</p>

<h4 id="4-follow-status">4. Follow status<a name="followstat"></a></h4>

<p>If the author check comes back with a value we use a simple <code class="highlighter-rouge">if</code> statement to initialise the database query for the follow status. A comprehensive tutorial is available to retrieve a list of followers and users that are being followed in the tutorial specified in the <code class="highlighter-rouge">intro</code>. As we are only interested in a very specific author we can narrow the query results down to a single result. That result then determines what the available actions are.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#result from previous step
</span><span class="k">if</span> <span class="n">result</span> <span class="p">:</span>
	<span class="c1">#check for author name in the current following list
</span>	<span class="n">follow</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get_following</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">author</span><span class="p">,</span> <span class="s">'blog'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">follow</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">follow</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">'following'</span><span class="p">]</span> <span class="o">==</span> <span class="n">author</span> <span class="p">:</span>
		<span class="n">title</span> <span class="o">=</span> <span class="s">"Author is already being followed, please choose action"</span>
	<span class="k">else</span><span class="p">:</span>
		<span class="n">title</span> <span class="o">=</span> <span class="s">"Author has not yet been followed, please choose action"</span>
<span class="k">else</span><span class="p">:</span>
	<span class="k">print</span><span class="p">(</span><span class="s">'Author does not exist'</span><span class="p">)</span>
	<span class="nb">exit</span><span class="p">()</span>
</code></pre></div></div>

<p>The result from the <code class="highlighter-rouge">follow</code> query is printed on the UI and the user is asked to select the next action to take based on that information. If the author does not exit the program exits automatically.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#get index and selected action
</span><span class="n">options</span> <span class="o">=</span> <span class="p">[</span><span class="s">'Follow'</span><span class="p">,</span> <span class="s">'Unfollow'</span><span class="p">,</span> <span class="s">'Exit'</span><span class="p">]</span>
<span class="n">option</span><span class="p">,</span> <span class="n">index</span> <span class="o">=</span> <span class="n">pick</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">title</span><span class="p">)</span>
</code></pre></div></div>

<p>Once we know what the user wants to do, we can move on to the actual <code class="highlighter-rouge">commit</code> to the blockchain.</p>

<h4 id="5-followunfollow-commit">5. Follow/Unfollow commit<a name="commit"></a></h4>

<p>Once the user has selected which action to take we user another <code class="highlighter-rouge">if</code> statement to execute that selection.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="n">option</span> <span class="o">==</span> <span class="s">'Follow'</span> <span class="p">:</span>
	<span class="n">s</span><span class="o">.</span><span class="n">commit</span><span class="o">.</span><span class="n">follow</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="p">[</span><span class="s">'blog'</span><span class="p">],</span> <span class="n">username</span><span class="p">)</span>
	<span class="k">print</span><span class="p">(</span><span class="n">author</span> <span class="o">+</span> <span class="s">' is now being followed'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
	<span class="k">if</span> <span class="n">option</span> <span class="o">==</span> <span class="s">'Unfollow'</span> <span class="p">:</span>
		<span class="n">s</span><span class="o">.</span><span class="n">commit</span><span class="o">.</span><span class="n">unfollow</span><span class="p">(</span><span class="n">author</span><span class="p">,</span> <span class="p">[</span><span class="s">'blog'</span><span class="p">],</span> <span class="n">username</span><span class="p">)</span>
		<span class="k">print</span><span class="p">(</span><span class="n">author</span> <span class="o">+</span> <span class="s">' has now been unfollowed'</span><span class="p">)</span>
	<span class="k">else</span><span class="p">:</span>
		<span class="k">print</span><span class="p">(</span><span class="s">'Action Cancelled'</span><span class="p">)</span>
</code></pre></div></div>

<p>A simple confirmation of the chosen action is printed on the screen.</p>

<p>You can also check on the <a href="http://condenser.steem.vc/blog/@cdemo">testportal</a> for a list of the authors being followed by the demo account.</p>

<h3 id="to-run-the-tutorial">To Run the tutorial</h3>

<ol>
  <li><a href="getting_started.html">review dev requirements</a></li>
  <li><code class="highlighter-rouge">git clone https://gitlab.syncad.com/hive/devportal.git</code></li>
  <li><code class="highlighter-rouge">cd devportal/tutorials/python/18_follow_a_user</code></li>
  <li><code class="highlighter-rouge">pip install -r requirements.txt</code></li>
  <li><code class="highlighter-rouge">python index.py</code></li>
  <li>After a few moments, you should see a prompt for input in terminal screen.</li>
</ol>

<hr />

</section>

</div>
<div class="footer">
  <a href="#">Back to top</a>
</div>
<script>
    document.getElementById("open-nav").addEventListener("click", function () {
        document.body.classList.toggle("nav-open");
    });
</script>
</body>
</html>


<script src="/js/adjust.js"></script>

